﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows.Controls.Ribbon;
using SHomeWorkshop.LunarConcept.Controls;
using System.Xml;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.ModifingManager;
using System.Windows;
using SHomeWorkshop.LunarConcept.Widgets;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;
using SHomeWorkshop.LunarConcept.Enums;

namespace SHomeWorkshop.LunarConcept.Commands
{
    /// <summary>
    /// 创建时间：2012年1月16日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：在当前主编辑器中移动部件的某个控制点坐标。
    /// </summary>
    public static class MoveWidgetControlerCommand
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态][构造方法]
        /// 
        /// ——此方法会初始化并向WPF系统注册一个RoutedUICommand。
        /// </summary>
        static MoveWidgetControlerCommand()//类型构造器
        {
            routedUICmd = new RoutedUICommand(
                "MoveWidgetControlerCommand",
                "MoveWidgetControlerCommand",
                typeof(MoveWidgetControlerCommand),//创建RoutedUICommand对象
                null);//本程序考虑支持“命令模式”因此，这些命令完全没有必要直接支持快捷键。

            cmdBinding.Command = routedUICmd;
            cmdBinding.CanExecute += new CanExecuteRoutedEventHandler(cmdBinding_CanExecute);
            cmdBinding.Executed += new ExecutedRoutedEventHandler(cmdBinding_Executed);
        }

        #endregion

        #region 字段与属性===================================================================================================

        private static CommandBinding cmdBinding = new CommandBinding();
        /// <summary>
        /// 用在主窗口CommandBindings集合中的命令绑定。
        /// 
        /// 它的Command是RoutedUICommand。
        /// ——因此，RoutedUICommand是否可以运行将由CmdBinding的CanExecute事件决定。
        /// ——而且，RoutedUICommand的执行也是通过CmdBinding的Execute事件来进行的。
        /// </summary>
        public static CommandBinding CmdBinding
        {
            get { return cmdBinding; }
        }

        private static RoutedUICommand routedUICmd;
        /// <summary>
        /// [只读静态属性]表示在WPF系统中注册的一个RoutedUICommand。
        /// ——必须和CommandBinding配合才能使用。
        ///     CommandBinding要添加到主窗口的CommandBindings集合中；
        ///     RoutedUICommand则要向WPF系统注册。
        ///     
        /// ★说明：使用静态属性是因为这样在Xaml代码中比较便于绑定。
        /// </summary>
        public static RoutedUICommand RoutedUICmd
        {
            get { return routedUICmd; }
        }

        #endregion

        #region 方法=========================================================================================================

        /// <summary>
        /// 判断命令是否可以执行。
        /// ——由于可以直接调用Execute()方法，因此，即使被禁用，也不是不能执行相关功能！！！
        /// </summary>
        static void cmdBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            //考虑到性能问题，全部取消此判断。反正执行时会判断。
            //if (Globals.MainWindow == null)
            //{
            //    e.CanExecute = false; return;
            //}

            //EditorManager manager = Globals.MainWindow.EditorManager;
            //if (manager == null)
            //{
            //    e.CanExecute = false; return;
            //}

            //if (manager.GetSelectedWidgetsCount() <= 0)
            //{
            //    e.CanExecute = false;
            //    return;
            //}

            e.CanExecute = true;
            return;
        }

        /// <summary>
        /// 命令被触发时，会调用本事件处理器方法。
        /// ——本方法实际上是调用ExeCute()这个静态方法来实现特定功能。
        /// </summary>
        static void cmdBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            //Execute();
        }

        /// <summary>
        /// [公开静态方法]即使此命令处于禁用状态，也可以通过代码调用此方法来执行特定任务！！！
        /// 
        /// 当被绑定的命令被调用（触发）时，会引发cmdBinding_Executed事件。
        /// 在cmdBinding_Executed事件处理器方法中已添加了调用Execute()方法的代码。
        /// 
        /// ——因此，触发命令，就相当于调用此方法！！！
        /// </summary>
        public static string Execute(MouseLeftButtonDraggingEventArgs e)
        {
            if (e == null || e.MasterPageEditor == null)
                return "　　未传入MouseLeftButtonDraggingEventArgs参数，或者未指定页面。";

            EditorManager manager = e.MasterPageEditor.MasterManager;
            if (manager == null) return "　　未找到页面管理器。";

            Widgets.Widget w = e.MainSelectedWidget;
            if (w == null) return "　　未找到活动部件。";

            Widgets.LineWidget lw = w as Widgets.LineWidget;
            if (lw == null) return "　　活动部件不是线型部件。";

            if (lw.IsLocked)
            {
                lw.RefreshLocation();
                return "　　此线型部件已被锁定，无法更改控制点位置。";
            }

            ILinkableLine linkedLine = lw as ILinkableLine;
            if (linkedLine != null && linkedLine.IsLinked &&
                    (linkedLine.DraggingType == ControlDraggingType.Start ||    //这些情形下，如是连接线，则应自动定位。
                     linkedLine.DraggingType == ControlDraggingType.End ||      //直线、曲线、折线的首尾控制点被拖动    
                     linkedLine.DraggingType == ControlDraggingType.CenterCP)   //折线的中控制点被拖动
                )
            {
                //看能否换个主子（挂接目标部件）。
                if (linkedLine.DraggingType != ControlDraggingType.CenterCP)    //折线作连接线时，中控制点只自动定位，不会换挂接对象。
                {
                    string tryResult = TrytoChangeMasterWidget(manager, linkedLine, e.EndPoint);
                    if (tryResult != string.Empty)
                    {
                        linkedLine.RefreshLocation();
                    }
                    return tryResult;
                }

                linkedLine.RefreshLocation();
                return string.Empty;
            }

            ModifingInfo info = new ModifingInfo();
            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);
            manager.GetSelectedWidgetStatus_New(info);

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            lw.DropWidgetControler(e.EndPoint, mi);
            lw.RefreshIsSelected();

            if (lw.MasterEditor != null && lw.MasterEditor.MasterManager != null)
            {
                lw.MasterEditor.MasterManager.RegisterModifingItem(mi);
                if (lw is ShapeWidget)
                {
                    lw.MasterEditor.MasterManager.RefreshAutoNumberStrings();
                    //只有ShapeWidget才需要,ArrowLineWidget不需要刷新自动编号。
                }
            }

            return string.Empty;
        }

        private static string TrytoChangeMasterWidget(EditorManager manager, ILinkableLine linkedLine, Point newPoint)
        {
            if (linkedLine == null) return "　　未传入linkedLine。";
            if (linkedLine.MasterEditor == null) return "　　未传入linkedLine.MasterEdiror。";
            if (linkedLine.MasterEditor.MasterManager == null) return "　　未找到页面管理器。";

            ModifingInfo info = new ModifingInfo();
            manager.GetSelectedPageEditorStatus(info);
            manager.GetSelectedWidgetStatus_Old(info);
            manager.GetSelectedWidgetStatus_New(info);

            ModifingItem<Action, ModifingInfo> mi = new ModifingItem<Action, ModifingInfo>(info);

            switch (linkedLine.DraggingType)
            {
                case ControlDraggingType.Start:
                    {
                        //寻找落点所在的部件。
                        ICanBeLinkedWidget iclwAtStopPoint = null;

                        foreach (Widgets.Widget w in linkedLine.MasterEditor.Children)
                        {
                            ICanBeLinkedWidget iclw = w as ICanBeLinkedWidget;
                            if (iclw == null || iclw.Id == linkedLine.StartMasterId) continue;

                            if (iclw.OuterRect.Contains(newPoint))
                            {
                                iclwAtStopPoint = iclw;
                                break;
                            }
                        }

                        if (iclwAtStopPoint == null) return "　　未找到首端点要挂接到的另一个部件。";
                        if (iclwAtStopPoint.Id == linkedLine.EndMasterId)//不允许两个端点挂接到同一个部件。
                            return "　　不允许两个端点连接到同一个部件。";

                        Action act = new Action(linkedLine.MasterEditor.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartMasterIdTag,
                                linkedLine.StartMasterId, iclwAtStopPoint.Id);

                        linkedLine.StartMasterId = iclwAtStopPoint.Id;

                        mi.AddAction(act);

                        //重新计算两个端点的坐标。
                        Widget endMaster = linkedLine.MasterEditor.GetWidget(linkedLine.EndMasterId);
                        if (endMaster != null)
                        {
                            //Rect startRect = iclwAtStopPoint.OuterRect;
                            //Rect endRect = endMaster.OuterRect;
                            //Point startCenter = new Point(startRect.Left + startRect.Width / 2,
                            //                        startRect.Top + startRect.Height / 2);
                            //Point endCenter = new Point(endRect.Left + endRect.Width / 2,
                            //                        endRect.Top + endRect.Height / 2);

                            //Tools.PointToRect.ArrowPoints aptStart = Tools.PointToRect.GetCrossPointToRect(startRect, endCenter);
                            //Tools.PointToRect.ArrowPoints aptEnd = Tools.PointToRect.GetCrossPointToRect(endRect, startCenter);

                            //Action actStartPoint = new Action(linkedLine.MasterEditor.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                            //    linkedLine.StartPoint.ToString(), aptStart.Top.ToString());
                            //linkedLine.StartPoint = aptStart.Top;

                            //mi.AddAction(actStartPoint);

                            //Action actEndPoint = new Action(linkedLine.MasterEditor.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                            //    linkedLine.EndPoint.ToString(), aptEnd.Top.ToString());
                            //linkedLine.EndPoint = aptEnd.Top;

                            //mi.AddAction(actEndPoint);

                            List<ILinkableLine> list = new List<ILinkableLine>();
                            list.Add(linkedLine);
                            linkedLine.MasterEditor.RefreshLinkedLines(mi, list);
                        }

                        linkedLine.MasterEditor.MasterManager.RegisterModifingItem(mi);

                        break;
                    }
                case ControlDraggingType.End:
                    {
                        //寻找落点所在的部件。
                        ICanBeLinkedWidget iclwAtStopPoint = null;

                        foreach (Widgets.Widget w in linkedLine.MasterEditor.Children)
                        {
                            ICanBeLinkedWidget iclw = w as ICanBeLinkedWidget;
                            if (iclw == null || iclw.Id == linkedLine.EndMasterId) continue;

                            if (iclw.OuterRect.Contains(newPoint))
                            {
                                iclwAtStopPoint = iclw;
                                break;
                            }
                        }


                        if (iclwAtStopPoint == null) return "　　未找到首端点要挂接到的另一个部件。";
                        if (iclwAtStopPoint.Id == linkedLine.EndMasterId)//不允许两个端点挂接到同一个部件。
                            return "　　不允许两个端点连接到同一个部件。";

                        Action act = new Action(linkedLine.MasterEditor.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartMasterIdTag,
                            linkedLine.EndMasterId, iclwAtStopPoint.Id);

                        linkedLine.EndMasterId = iclwAtStopPoint.Id;

                        mi.AddAction(act);

                        //重新计算两个端点的坐标。
                        Widget startMaster = linkedLine.MasterEditor.GetWidget(linkedLine.StartMasterId);
                        if (startMaster != null)
                        {
                            //Rect startRect = startMaster.OuterRect;
                            //Rect endRect = iclwAtStopPoint.OuterRect;

                            //Point startCenter = new Point(startRect.Left + startRect.Width / 2,
                            //                        startRect.Top + startRect.Height / 2);
                            //Point endCenter = new Point(endRect.Left + endRect.Width / 2,
                            //                        endRect.Top + endRect.Height / 2);

                            //Tools.PointToRect.ArrowPoints aptStart = Tools.PointToRect.GetCrossPointToRect(startRect, endCenter);
                            //Tools.PointToRect.ArrowPoints aptEnd = Tools.PointToRect.GetCrossPointToRect(endRect, startCenter);

                            //Action actStartPoint = new Action(linkedLine.MasterEditor.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.StartPointTag,
                            //    linkedLine.StartPoint.ToString(), aptStart.Top.ToString());
                            //linkedLine.StartPoint = aptStart.Top;

                            //mi.AddAction(actStartPoint);

                            //Action actEndPoint = new Action(linkedLine.MasterEditor.Id, linkedLine.Id, linkedLine.GetType().Name, XmlTags.EndPointTag,
                            //    linkedLine.EndPoint.ToString(), aptEnd.Top.ToString());
                            //linkedLine.EndPoint = aptEnd.Top;

                            //mi.AddAction(actEndPoint);

                            List<ILinkableLine> list = new List<ILinkableLine>();
                            list.Add(linkedLine);
                            linkedLine.MasterEditor.RefreshLinkedLines(mi, list);
                        }

                        linkedLine.MasterEditor.MasterManager.RegisterModifingItem(mi);

                        break;
                    }
            }
            return string.Empty;
        }

        #endregion
    }
}
